package cc.wanforme.fsync.server;

import cc.wanforme.fsync.entity.*;
import cc.wanforme.fsync.entity.po.*;
import cc.wanforme.fsync.server.service.IGroupMapService;
import cc.wanforme.fsync.server.service.ISyncLogService;
import cc.wanforme.fsync.server.service.ITickTaskGroupService;
import cc.wanforme.fsync.server.service.ITickTaskService;
import cc.wanforme.st.server.vo.ResMessage;
import cn.dev33.satoken.annotation.SaCheckLogin;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/server")
public class ServerController {
    private ServerCenter center;
    private IGroupMapService groupMapService;
    private ITickTaskService taskService;
    private ITickTaskGroupService taskGroupService;

    private ISyncLogService syncLogService;

    // 连接客户端，并获取到设备信息
    @PostMapping("/connect")
    @SaCheckLogin
    @ResponseBody
    public ResMessage<Void> connect(@RequestBody ClientNode node) {
        center.connectClient(node);
        return ResMessage.success();
    }

//    // 更新同步文件的配置
//    @PostMapping("/config")
//    @ResponseBody
//    public ResMessage<Void> syncConfig(@RequestBody SyncConfig config) {
//        center.updateSyncConfig(config);
//        return ResMessage.success();
//    }

    /** 同步单个文件 或 文件夹 */
    @PostMapping("/async")
    @SaCheckLogin
    @ResponseBody
    public ResMessage<String> syncFolder(@RequestBody SyncMeta syncMeta) throws Exception {
        return center.async(syncMeta, LocalDateTime.now());
    }

    /** 手动同步单个文件 */
    @PostMapping("/sync-file")
    @SaCheckLogin
    @ResponseBody
    public ResMessage<String> syncFile(@RequestBody SyncMeta syncMeta) throws Exception {
        SyncMetaDto dto = SyncMetaDto.from(syncMeta, null, null);
        return center.syncFile(dto, LocalDateTime.now());
    }

    /** server 端自己路径下的文件，只需要 path参数 */
    @PostMapping("/list")
    @SaCheckLogin
    @ResponseBody
    public ResMessage<List<FileInfoVo>> listFiles(@RequestBody FileInfo path) {
        List<FileInfo> infos = FileInfo.listFiles(path.getPath());
        List<FileInfoVo> vos = new ArrayList<>(0);
        if(infos!=null) {
            vos = infos.stream().map(FileInfoVo::new).collect(Collectors.toList());
        }
        return ResMessage.success(vos);
    }

    /** client 端路径下的文件 */
    @PostMapping("/list-client")
    @SaCheckLogin
    @ResponseBody
    public ResMessage<List<FileInfoVo>> listClientFiles(@RequestBody DirReqVo vo) {
        ResMessage<List<FileInfoVo>> res = center.listClientFiles(vo.getNode(), vo.getPath());
        return res;
    }

    // ============================

    /** 所有客户端 */
    @PostMapping("/client/list")
    @SaCheckLogin
    @ResponseBody
    public ResMessage<ConcurrentLinkedDeque<ClientNodeInfo>> clients() {
        ConcurrentLinkedDeque<ClientNodeInfo> clients = center.getClients();
        return ResMessage.success(clients);
    }

    @PostMapping("/client/get/{id}")
    @SaCheckLogin
    @ResponseBody
    public ResMessage<ClientNodeInfo> clientInfo(@PathVariable Long id) {
        ClientNodeInfo info = center.getInfoById(id);
        return ResMessage.success(info);
    }

    /** 更新客户端信息 */
    @PostMapping("/client/update")
    @SaCheckLogin
    @ResponseBody
    public ResMessage<Void> updateClient(@RequestBody ClientNode node) {
        center.updateClientById(node);
        return ResMessage.success();
    }

    /** 更新客户端信息 */
    @PostMapping("/client/del/{id}")
    @SaCheckLogin
    @ResponseBody
    public ResMessage<Void> deleteClient(@PathVariable Long id) {
        center.deleteClientById(id);
        return ResMessage.success();
    }

    // ============================

    /** 所有 group-map 的 name */
    @PostMapping("/group/names")
    @SaCheckLogin
    @ResponseBody
    public ResMessage<List<String>> groups() {
        List<String> groups = groupMapService.groups();
        return ResMessage.success(groups);
    }
    /** group-map 的所有详细，只需要 name 参数  */
    @PostMapping("/group/list")
    @SaCheckLogin
    @ResponseBody
    public ResMessage<List<GroupMapVo>> groupList(@RequestBody GroupMap name) {
        List<GroupMapVo> list = center.listGroupMaps(name.getName());
        return ResMessage.success(list);
    }

    /** 创建 group-map */
    @PostMapping("/group/add")
    @SaCheckLogin
    @ResponseBody
    public ResMessage<GroupMap> groupAdd(@RequestBody GroupMap vo) {
        GroupMap po = groupMapService.saveVo(vo);
        return ResMessage.success(po);
    }
    /** 更新 group-map */
    @PostMapping("/group/update")
    @SaCheckLogin
    @ResponseBody
    public ResMessage<GroupMap> groupUpdate(@RequestBody GroupMap vo) {
        GroupMap po = groupMapService.updateVo(vo);
        return ResMessage.success(po);
    }
    /** 删除 group-map */
    @PostMapping("/group/del/{id}")
    @SaCheckLogin
    @ResponseBody
    public ResMessage<Void> groupDel(@PathVariable("id") Long id) {
        taskGroupService.deleteByGroupMap(id);
        groupMapService.removeById(id);
        return ResMessage.success();
    }

    // ============================

    /** 所有 task  */
    @PostMapping("/task/list")
    @SaCheckLogin
    @ResponseBody
    public ResMessage<List<TickTask>> taskList() {
        List<TickTask> list = taskService.list();
        return ResMessage.success(list);
    }
    /** task 所有的 GroupMap 信息  */
    @PostMapping("/task-groupMaps/{id}")
    @SaCheckLogin
    @ResponseBody
    public ResMessage<List<GroupMapVo>> taskGroups(@PathVariable Long id) {
        List<GroupMapVo> list = taskGroupService.listInfoByTask(id);
        return ResMessage.success(list);
    }
    /** 创建 task */
    @PostMapping("/task/add")
    @SaCheckLogin
    @ResponseBody
    public ResMessage<TickTask> taskAdd(@RequestBody TickTask vo) {
        TickTask po = taskService.saveVo(vo);
        return ResMessage.success(po);
    }
    /** 更新 task */
    @PostMapping("/task/update")
    @SaCheckLogin
    @ResponseBody
    public ResMessage<TickTask> taskUpdate(@RequestBody TickTask vo) {
        TickTask po = taskService.updateVo(vo);
        return ResMessage.success(po);
    }
    /** 删除 task */
    @PostMapping("/task/del/{id}")
    @SaCheckLogin
    @ResponseBody
    public ResMessage<Void> taskDel(@PathVariable("id") Long id) {
        taskService.deleteVo(id);
        return ResMessage.success();
    }

    /** 创建 task-groupMap */
    @PostMapping("/task/groupMap-add")
    @SaCheckLogin
    @ResponseBody
    public ResMessage<TickTaskGroup> taskGroupAdd(@RequestBody TickTaskGroup vo) {
        TickTaskGroup po = taskGroupService.saveVo(vo);
        return ResMessage.success(po);
    }
    /** 删除 task-groupMap */
    @PostMapping("/task/groupMap-del")
    @SaCheckLogin
    @ResponseBody
    public ResMessage<Void> taskGroupDel(@RequestBody TickTaskGroup vo ) {
        taskGroupService.deleteByVo(vo);
        return ResMessage.success();
    }
    /** 删除 task-groupMap */
    @PostMapping("/task/active")
    @SaCheckLogin
    @ResponseBody
    public ResMessage<Void> taskGroupDel(@RequestBody TickTask vo ) {
        taskService.changeActive(vo.getId(), vo.getActive(), true);
        return ResMessage.success();
    }

    @PostMapping("/logs")
    @SaCheckLogin
    @ResponseBody
    public ResMessage<List<SyncLog>> taskGroupDel(@RequestParam(defaultValue = "20") int size) {
        List<SyncLog> logs = syncLogService.listLatest(size);
        return ResMessage.success(logs);
    }

    @Autowired
    public void setCenter(ServerCenter center) {
        this.center = center;
    }
    @Autowired
    public void setGroupMapService(IGroupMapService groupMapService) {
        this.groupMapService = groupMapService;
    }
    @Autowired
    public void setTaskService(ITickTaskService taskService) {
        this.taskService = taskService;
    }
    @Autowired
    public void setTaskGroupService(ITickTaskGroupService taskGroupService) {
        this.taskGroupService = taskGroupService;
    }
    @Autowired
    public void setSyncLogService(ISyncLogService syncLogService) {
        this.syncLogService = syncLogService;
    }
}
